package com.gable.exhibition.service.impl;

import com.alibaba.fastjson.JSON;
import com.gable.common.util.ReturnResultUtil;
import com.gable.common.util.UUIDGenerator;
import com.gable.exhibition.dao.*;
import com.gable.exhibition.model.*;
import com.gable.exhibition.service.ContractEstimateSendService;
import com.gable.exhibition.service.SequenceService;
import com.gable.exhibition.thread.ChatGroupThread;
import com.gable.exhibition.thread.EstimateSendDispatchSmsThread;
import com.gable.exhibition.thread.EstimateSendSmsThread;
import com.gable.exhibition.util.ExceptionUtil;
import com.gable.exhibition.util.MessageUtil;
import com.gable.exhibition.view.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by mj on 2018/2/6.
 */
@Service
public class ContractEstimateSendServiceImpl implements ContractEstimateSendService {

    @Value("${remindDay}")
    Integer remindDay;

    @Value("${serviceSendNoInstall}")
    String serviceSendNoInstall; //发货不需要安装推送给医院短信URL

    @Value("${sendByDoctor}")
    String sendByDoctor;        //发货需要安装推送给医院短信URL

    @Value("${serviceSendByEngineer}")
    String serviceSendByEngineer;   //发货指派工程师推送给工程师短信URL

    @Value("${sendAssignService}")
    String sendAssignService;       // 发货指派给其他服务商

    @Value("${webSocket_InsertSendUrl}")
    String webSocket_InsertSendUrl; //发货流程产生群组

    @Autowired
    ContractEstimateSendDao contractEstimateSendDao;

    @Autowired
    ContractDeviceEstimateSendDao contractDeviceEstimateSendDao;

    @Autowired
    ContractActualSendDao contractActualSendDao;

    @Autowired
    ContractDeviceActualSendDao contractDeviceActualSendDao;

    @Autowired
    ContractDao contractDao;

    @Autowired
    InstallDao installDao;

    @Autowired
    UserDao userDao;

    @Autowired
    ContractDeviceDao contractDeviceDao;

    @Autowired
    SequenceService sequenceService;

    @Autowired
    EventDao eventDao;

    @Autowired
    ManufacturerMaintainerDao manufacturerMaintainerDao;

    @Autowired
    SupplierDao supplierDao;

    @Autowired
    AppointDao appointDao;

    @Autowired
    MaintainerDao maintainerDao;

    @Override
    public ReturnResultUtil querySendRemind(ParameterView parameterView) {
        Map<String,Object> map = new HashMap<String,Object>();

        parameterView.setRemindDay(remindDay);
        Long manufacturerId = parameterView.getManufacturerId();
        //厂商登录，查询其下的厂商供应商，获取发货列表
        if(manufacturerId != null){
            Supplier supplier = supplierDao.queryManufacturerSupplier(manufacturerId);
            parameterView.setSupplierId(0L);
            if(supplier != null)
                parameterView.setSupplierId(supplier.getSupplierId());
        }
        Integer count = contractEstimateSendDao.queryRemindCount(parameterView);
        if(count > 0){
            List<ContractView> contractViews = contractEstimateSendDao.queryRemind(parameterView);
            for(ContractView contractView : contractViews){
                Long contractEstimateSendId = contractView.getContractEstimateSendId();
                List<ModelView> modelViews = contractEstimateSendDao.waitSendModel(contractEstimateSendId);
                contractView.setModelList(modelViews);
            }
            map.put("data",contractViews);
        }
        map.put("count",count);

        return new ReturnResultUtil(200, MessageUtil.QUERYSUCCESS,map);
    }

    @Override
    public ReturnResultUtil waitSend(ParameterView parameterView) {
        Map<String,Object> map = new HashMap<String,Object>();
        Long manufacturerId = parameterView.getManufacturerId();
        //厂商登录，查询其下的厂商供应商，获取发货列表
        if(manufacturerId != null){
            Supplier supplier = supplierDao.queryManufacturerSupplier(manufacturerId);
            parameterView.setSupplierId(0L);
            if(supplier != null)
                parameterView.setSupplierId(supplier.getSupplierId());
        }
        Integer count = contractEstimateSendDao.waitSendCount(parameterView);
        if(count > 0){
            List<ContractView> contractViews = contractEstimateSendDao.waitSend(parameterView);
            for(ContractView contractView : contractViews){
                Long contractEstimateSendId = contractView.getContractEstimateSendId();
                List<ModelView> modelViews = contractEstimateSendDao.waitSendModel(contractEstimateSendId);
                contractView.setModelList(modelViews);
            }
            map.put("data",contractViews);
        }
        map.put("count",count);
        return new ReturnResultUtil(200,MessageUtil.QUERYSUCCESS,map);
    }

    @Override
    public ReturnResultUtil waitSendInfo(ParameterView parameterView) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        ContractView contractView = contractEstimateSendDao.waitSendInfo(parameterView);
        Integer whetherNeedInstall = contractView.getWhetherNeedInstall();
        //发货单下有需要安装的设备，需要带出维修商列表
        if(whetherNeedInstall > 0){
            Long secondParty = contractView.getSecondParty();   //厂商ID
            List<ManufacturerMaintainerView> manufacturerMaintainers = manufacturerMaintainerDao.getListByManufacturerId(secondParty);
            contractView.setManufacturerMaintainers(manufacturerMaintainers);
        }
        Long aLong = sequenceService.querySequence();
        String manufacturerNo = contractView.getManufacturerNo()==null?"000000":contractView.getManufacturerNo();
        String sendNo = manufacturerNo+sdf.format(new Date())+aLong;
        contractView.setSendNo(sendNo);
        return new ReturnResultUtil(200,MessageUtil.QUERYSUCCESS,contractView);
    }

    @Override
    @Transactional
    public synchronized ReturnResultUtil sendForEstimate(SendParameterView sendParameterView) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Long contractEstimateSendId = sendParameterView.getContractEstimateSendId();    //预计发货单ID
        Long contractId = sendParameterView.getContractId();    //合同ID
        String sendDate = sendParameterView.getSendDate();      //发货日期
        String sendNo = sendParameterView.getSendNo();  //发货单号
        String sendDeviceJson = sendParameterView.getSendDeviceJson();  //发货设备
        String projectChargePerson = sendParameterView.getProjectChargePerson();//工程师名称
        String projectChargePersonPhone = sendParameterView.getProjectChargePersonPhone();//工程师电话
        String estimateInstallDate = sendParameterView.getEstimateInstallDate();//预计安装时间
        Integer oneself = sendParameterView.getOneself();       //是否自身派工

        Long contractActualSendId = UUIDGenerator.getUniqueLong();    //实际发货单主键ID
        //合同信息
        ContractView contract = contractDao.queryContractForSendSms(contractId);
        if(contract == null)
            return new ReturnResultUtil(500,MessageUtil.CONTRACTNOEXIST);
        //预计发货单信息
        ContractEstimateSend contractEstimateSend = contractEstimateSendDao.selectByPrimaryKey(contractEstimateSendId);
        if(contractEstimateSend == null)
            return new ReturnResultUtil(500,MessageUtil.CONTRACTESTIMATESENDNOEXIST);

        //实际发货单信息
        ContractActualSend contractActualSend = new ContractActualSend();
        //选择服务商类型 1102厂商 1103维修商
        Maintainer maintainer = null;
        Long serviceType = sendParameterView.getServiceType();

        //指派记录
        Appoint appoint = new Appoint();
        appoint.setAppointId(UUIDGenerator.getUniqueLong());
        appoint.setKeyId(contractActualSendId);
        appoint.setKeyType(2903L);  //发货安装
        Long manufacturerId = sendParameterView.getManufacturerId();
        Long supplierId = sendParameterView.getSupplierId();
        if(manufacturerId != null){
            appoint.setInstructId(manufacturerId);
            appoint.setInstructType(1102L);
        }else if(supplierId != null){
            appoint.setInstructId(supplierId);
            appoint.setInstructType(1105L);
        }
        appoint.setCreatePerson(sendParameterView.getUserId());
        appoint.setInstructedType(serviceType);
        appoint.setInstructedId(sendParameterView.getServiceId());
        appoint.setEngineerName(projectChargePerson);
        appoint.setEngineerPhone(projectChargePersonPhone);
        if(oneself == 0){
            if(serviceType.intValue() == 1103){
                String serviceName = sendParameterView.getServiceName();
                Maintainer maintainerParameter = new Maintainer();
                maintainerParameter.setMaintainerName(serviceName);
                maintainer = maintainerDao.checkMaintainer(maintainerParameter);
                if(maintainer == null){
                    maintainer = new Maintainer();
                    maintainer.setMaintainerId(UUIDGenerator.getUniqueLong());
                    maintainer.setMaintainerName(serviceName);
                    maintainer.setRemark("发货创建维修商");
                    maintainer.setMaintainerContacts(sendParameterView.getMaintainerContacts());
                    maintainer.setMaintainerPhone(sendParameterView.getMaintainerPhone());
                    maintainer.setCreatePerson(sendParameterView.getUserId());
                    maintainer.setIsDel(1); //流程创建线下维修商
                    int i = maintainerDao.insertSelective(maintainer);
                    if(i == 0)
                        return new ReturnResultUtil(500,MessageUtil.MAINTAINERCREATEERROR);
                }
                User userParameter = new User();
                userParameter.setMobile(projectChargePersonPhone);
                userParameter.setUserName(projectChargePersonPhone);
                User user = userDao.checkUserByEngineerPhone(userParameter);
                if(user == null){
                    user = new User();
                    user.setMaintainerId(maintainer.getMaintainerId());
                    user.setUserId(UUIDGenerator.getUniqueLong());
                    user.setUserName(projectChargePersonPhone);
                    user.setMobile(projectChargePersonPhone);
                    user.setRealName(projectChargePerson);
                    user.setType(serviceType);    //1102厂商 1103维修商 1105供应商
                    user.setTag(1006L); //维修商工程师
                    user.setRemark("安装派工产生用户");
                    int row5 = userDao.insertSelective(user);
                    if(row5 == 0)
                        throw new ExceptionUtil(500,MessageUtil.USERERROR,user);
                }
                appoint.setInstructedId(maintainer.getMaintainerId());

                //发货单绑定工程师ID
                contractActualSend.setProjectChargePersonId(user.getUserId());
                //发货单绑定服务商ID
                contractActualSend.setServiceId(maintainer.getMaintainerId());
            }
        }else
        //自身指派工程师
        if(oneself == 1){
            User userParameter = new User();
            userParameter.setMobile(projectChargePersonPhone);
            userParameter.setUserName(projectChargePersonPhone);
            User user = userDao.checkUserByEngineerPhone(userParameter);
            if(user == null){
                user = new User();
                Long userTag = 0L;
                if(serviceType.intValue() == 1102){
                    userTag = 1004L;        //厂商工程师
                    user.setManufacturerId(sendParameterView.getServiceId());
                }else if(serviceType.intValue() == 1105){
                    userTag = 1009L;        //供应商工程师
                    user.setSupplierId(sendParameterView.getServiceId());
                }

                user.setUserId(UUIDGenerator.getUniqueLong());
                user.setUserName(projectChargePersonPhone);
                user.setMobile(projectChargePersonPhone);
                user.setRealName(projectChargePerson);
                user.setType(serviceType);    //1102厂商  1105供应商
                user.setTag(userTag);
                user.setRemark("安装派工产生用户");
                int row5 = userDao.insertSelective(user);
                if(row5 == 0)
                    throw new ExceptionUtil(500,MessageUtil.USERERROR,user);
            }
            //发货单绑定工程师ID
            contractActualSend.setProjectChargePersonId(user.getUserId());
            //发货单绑定服务商ID
            contractActualSend.setServiceId(sendParameterView.getServiceId());
        }
        int row = appointDao.insertSelective(appoint);
        if(row == 0)
            throw new ExceptionUtil(500,MessageUtil.APPOINTERROR,appoint);

        //1.insert 产生实际发货单
        contractActualSend.setContractActualSendId(contractActualSendId);
        contractActualSend.setContractId(contractId);
        contractActualSend.setSendNo(sendNo);
        contractActualSend.setSendDate(sendDate);
        contractActualSend.setServiceType(serviceType);
        contractActualSend.setCreatePerson(sendParameterView.getUserId());
        int row1 = contractActualSendDao.insertSelective(contractActualSend);
        if(row1 == 0)
            throw new ExceptionUtil(500,MessageUtil.ACTUALINSERT,contractActualSend);

        //预计发货设备数据 [{contractDeviceId:xxx,actualQuantity:100,surplusQuantity:100,remark:xxx}]
        List<ContractDeviceEstimateSend> contractDeviceEstimateSends = JSON.parseArray(sendDeviceJson, ContractDeviceEstimateSend.class);

        Integer sendCountForSms = 0;        //统计短信所需的发货数量
        for(ContractDeviceEstimateSend contractDeviceEstimateSend : contractDeviceEstimateSends){
            Integer surplusQuantity = contractDeviceEstimateSend.getSurplusQuantity();      //剩余发货数量
            Integer actualSendQuantity = contractDeviceEstimateSend.getActualQuantity();    //本次发货数量
            sendCountForSms += actualSendQuantity;
            if(actualSendQuantity <= 0)
                throw new ExceptionUtil(500,MessageUtil.SENDCOUNT);
            //发货数量不能大于预计发货数量
            if(actualSendQuantity > surplusQuantity)
                throw new ExceptionUtil(500,MessageUtil.ACTUALQUANTITYERROR,contractDeviceEstimateSend);
            Long contractDeviceId = contractDeviceEstimateSend.getContractDeviceId();   //合同设备ID

            contractDeviceEstimateSend.setContractEstimateSendId(contractEstimateSendId);
            //根据发货单ID 和 合同设备ID 查询唯一记录
            List<ContractDeviceEstimateSendView> sendDevices = contractDeviceEstimateSendDao.selectContractDeviceEstimateSend(contractDeviceEstimateSend);
            ContractDeviceEstimateSendView sendDevice = sendDevices.get(0);
            Integer actualQuantity = sendDevice.getActualQuantity();//历史实际发货

            //2.预计发货设备 更新实际发货数量+ contractDeviceEstimateSend.getActualQuantity()
            contractDeviceEstimateSend.setActualQuantity(actualSendQuantity+actualQuantity);
            int row2 = contractDeviceEstimateSendDao.updateBySend(contractDeviceEstimateSend);
            if(row2 == 0)
                throw new ExceptionUtil(500,MessageUtil.ACTUALQUANTITYUPDATE,sendDevice);

            //3 insert 产生实际发货设备
            ContractDeviceActualSend contractDeviceActualSend = new ContractDeviceActualSend();
            contractDeviceActualSend.setContractDeviceActualSendId(UUIDGenerator.getUniqueLong());
            contractDeviceActualSend.setContractActualSendId(contractActualSendId);
            contractDeviceActualSend.setContractDeviceId(contractDeviceId);
            contractDeviceActualSend.setActualSendQuantity(actualSendQuantity);
            contractDeviceActualSend.setActualSendDate(sendDate);
            contractDeviceActualSend.setRemark(contractDeviceEstimateSend.getRemark());
            int row3 = contractDeviceActualSendDao.insertSelective(contractDeviceActualSend);
            if(row3 == 0)
                throw new ExceptionUtil(500,MessageUtil.DEVICEACTUALSEND,contractDeviceActualSend);
            //5. 回写合同设备实际发货数量
            ContractDevice contractDevice = contractDeviceDao.selectByPrimaryKey(contractDeviceId);
            contractDevice.setActualQuantity(contractDevice.getActualQuantity()+actualSendQuantity);
            int row6 = contractDeviceDao.updateByPrimaryKeySelective(contractDevice);
            if(row6 == 0)
                throw new ExceptionUtil(500,MessageUtil.UPDATECONTRACTACTUALQUANTITY,contractDevice);
            //4. 根据是否安装 产生安装派工 0false 1true
            Integer whetherNeedInstall = sendDevice.getWhetherNeedInstall();
            //产生安装派工,自身指派或者给维修商时直接产生派工
            //一个设备一个数量产生一条派工
            if(oneself == 1 || sendParameterView.getServiceType().intValue() == 1103){
                for(int i = 0;i<actualSendQuantity;i++){
                    Event event = new Event();
                    Install install = new Install();
                    install.setInstallId(UUIDGenerator.getUniqueLong());
                    install.setContractDeviceActualSendId(contractDeviceActualSend.getContractDeviceActualSendId());
                    install.setHospitalId(contract.getFirstParty());
                    install.setHospitalContacts(sendParameterView.getHospitalContacts());
                    install.setHospitalPhone(sendParameterView.getHospitalPhone());
                    install.setStatus(1202L);
                    install.setIsFictitious(1); //默认为虚拟安装单
                    install.setServiceType(serviceType);    //1102厂商 1103维修商 1105供应商
                    install.setServiceId(contractActualSend.getServiceId());

                    event.setEventTitle("设备发货等待验收");
                    event.setEventContent("设备:"+contractDevice.getDeviceName()+"于"+sendDate+"发货，等待验收");
                    event.setType(2403L);   //设备发货等待安装	设备事件类型

                    if(whetherNeedInstall == 1) {   //需要安装
                        install.setProjectChargePerson(projectChargePerson);
                        install.setProjectChargePersonPhone(projectChargePersonPhone);
                        install.setEstimateInstallDate(estimateInstallDate);
                        install.setStatus(1201L);//当需要安装时状态为待安装
                        install.setIsFictitious(0); //实际安装单
                        install.setDispatchRemark(sendParameterView.getDispatchRemark());
                        Long aLong = sequenceService.querySequence();
                        String installNo = sdf.format(new Date())+aLong;
                        install.setInstallNo(installNo);
                        event.setEventTitle("设备发货等待安装");
                        event.setEventContent("设备:"+contractDevice.getDeviceName()+"于"+sendDate+"发货，等待安装");
                        event.setType(2400L);   //设备发货等待安装	设备事件类型
                    }

                    int row4 = installDao.insertSelective(install);
                    if(row4 == 0)
                        throw new ExceptionUtil(500,MessageUtil.INSTALLERROR,install);

                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    event.setEventId(UUIDGenerator.getUniqueLong());
                    event.setKeyType(1600L);        //安装
                    event.setKeyId(install.getInstallId());
                    event.setEventDateTime(simpleDateFormat.format(new Date()));
                    event.setCreatePerson(sendParameterView.getUserId());
                    row = eventDao.insertSelective(event);
                    if(row == 0)
                        throw new ExceptionUtil(500,MessageUtil.INSERTEVENTERROR,event);
                }
            }
        }

        new Thread(new ChatGroupThread(contractActualSendId+"",webSocket_InsertSendUrl)).start();

        //推送 1：医院有一批设备已发货，2：工程师有安装信息
        String hospitalName = contract.getHospitalName();
        String supplierName = contract.getSupplierName();
        String contractNo = contract.getContractNo();
        //sendCountForSms
        List<String> hospitalMobile = contract.getMobileList();
        //指派自身工程师或维修商工程师
        if(oneself == 1 || sendParameterView.getServiceType().intValue() == 1103){
            String serviceName = "";
            if(sendParameterView.getServiceType().intValue() == 1103){
                serviceName = maintainer.getMaintainerName();
            }else{
                serviceName = sendParameterView.getSupplierName();
                if(!StringUtils.isEmpty(sendParameterView.getManufacturerName()))
                    serviceName = sendParameterView.getManufacturerName();
            }
            new Thread(new EstimateSendSmsThread(hospitalName,supplierName,contractNo,
                    sendCountForSms,hospitalMobile,projectChargePersonPhone,serviceName,
                    sendParameterView.getProjectChargePerson(),estimateInstallDate,serviceSendNoInstall,serviceSendByEngineer,sendByDoctor)).start();
        }
        //指派其他服务商
        else{
            new Thread(new EstimateSendDispatchSmsThread(hospitalName,supplierName,contractNo,contractActualSend.getServiceType(),contractActualSend.getServiceId(),userDao,sendAssignService)).start();
        }

        return new ReturnResultUtil(200,MessageUtil.SUCCESSFUL);
    }
}
